package de.slothsoft.bookmaker.parse;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPathExpressionException;

import org.htmlcleaner.CleanerProperties;
import org.htmlcleaner.DomSerializer;
import org.htmlcleaner.HtmlCleaner;
import org.htmlcleaner.TagNode;
import org.w3c.dom.Document;
import org.w3c.dom.xpath.XPathException;

import de.slothsoft.bookmaker.ProgressMonitor;
import de.slothsoft.bookmaker.pdf.PdfRequest;

public class ImageXPathParser implements WebsiteParser {

    public static ImageXPathParser createForMangaEden(String title, List<String> pageUrls) {
        return new ImageXPathParser(title, pageUrls, "//img[@id='mainImg']") {

            @Override
            protected String refineImage(String line) {
                return "https:" + super.refineImage(line);
            }
        };
    }

    public static ImageXPathParser createForMangaHere(String title, List<String> pageUrls) {
        return new ImageXPathParser(title, pageUrls, "//img[@id='image']");
    }

    private final String title;
    private final List<String> pageUrls;

    private final String xPath;

    private StreamProvider streamProvider = new DefaultStreamProvider();

    public ImageXPathParser(String title, List<String> pageUrls, String xPath) {
        this.title = title;
        this.pageUrls = pageUrls;
        this.xPath = xPath;
    }

    @Override
    public PdfRequest[] parse(ProgressMonitor monitor) throws IOException {
        List<String> imageUrls = new ArrayList<>(this.pageUrls.size());
        for (String pageUrl : this.pageUrls) {
            String imageUrl = findImageUrl(pageUrl);
            if (imageUrl != null) {
                String refinedImage = refineImage(imageUrl);
                imageUrls.add(refinedImage);
                monitor.setText("Found image URL: " + refinedImage);
            }
            monitor.incrementValue();
        }
        return new PdfRequest[] { new PdfRequest(this.title, imageUrls) };
    }

    private String findImageUrl(String pageUrl) throws IOException {
        try (InputStream input = this.streamProvider.createStream(pageUrl)) {
            TagNode tagNode = new HtmlCleaner().clean(input);
            Document document = new DomSerializer(new CleanerProperties()).createDOM(tagNode);
            return XPathUtil.findAttribute(document, this.xPath, "src");
        } catch (XPathException | ParserConfigurationException | XPathExpressionException e) {
            throw new IOException(e);
        }
    }

    protected String refineImage(String line) {
        return line;
    }

    public List<String> getPageUrls() {
        return this.pageUrls;
    }

    public String getTitle() {
        return this.title;
    }

    public StreamProvider getStreamProvider() {
        return this.streamProvider;
    }

    public void setStreamProvider(StreamProvider streamProvider) {
        this.streamProvider = streamProvider;
    }

}
